/**
 * ============错误处理中间件模块开始===========
 * 错误处理中间件 - Error Handler Middleware
 * 
 * 功能说明：
 * - 统一处理应用程序中的所有错误
 * - 提供标准化的错误响应格式
 * - 支持开发环境和生产环境的不同错误信息
 * - 集成日志记录功能
 * 
 * 依赖模块：
 * - logger: 日志记录工具，用于记录错误信息
 * 
 * 中间件特性：
 * - 全局错误捕获和处理
 * - 防止应用程序崩溃
 * - 标准化错误响应格式
 * - 环境相关的错误信息展示
 * 
 * 应用场景：
 * - 捕获路由处理器中的未处理错误
 * - 处理异步操作中的错误
 * - 提供用户友好的错误信息
 * - 记录错误日志用于调试和监控
 * 
 * 设计原则：
 * - 安全性优先，不泄露敏感信息
 * - 用户友好的错误提示
 * - 详细的错误日志记录
 * - 环境相关的错误处理策略
 * 
 * Provides comprehensive error handling with logging and environment-aware responses
 */

// 导入必要的依赖包 - Import necessary dependencies
import { logger } from "../utils/logger.js";                      // 日志记录工具 - Logging utility

/**
 * ============全局错误处理中间件开始===========
 * 全局错误处理中间件 - 统一处理应用程序错误
 * Global Error Handler Middleware - Unified application error handling
 * 
 * @param {Error} err - 错误对象，包含错误信息和堆栈跟踪
 * @param {Object} req - Express请求对象
 * @param {Object} res - Express响应对象
 * @param {Function} next - Express下一个中间件函数
 * @returns {void} 返回错误响应或传递给下一个错误处理器
 * 
 * 功能说明：
 * - 捕获应用程序中所有未处理的错误
 * - 记录详细的错误日志用于调试
 * - 根据环境返回适当的错误信息
 * - 防止错误导致应用程序崩溃
 * - 提供标准化的错误响应格式
 * 
 * 工作流程：
 * 1. 接收错误对象和请求上下文
 * 2. 记录错误日志到日志系统
 * 3. 检查响应是否已经发送
 * 4. 提取错误状态码和消息
 * 5. 构建标准化错误响应
 * 6. 根据环境决定是否包含堆栈信息
 * 
 * 错误类型处理：
 * - 业务逻辑错误：返回具体错误信息
 * - 系统错误：返回通用错误信息
 * - 验证错误：返回验证失败详情
 * - 数据库错误：返回数据操作错误信息
 * 
 * 响应格式：
 * {
 *   "success": false,
 *   "message": "错误描述信息",
 *   "error": "ERROR_CODE",
 *   "timestamp": "2024-01-01T00:00:00.000Z",
 *   "path": "/api/endpoint",
 *   "stack": "错误堆栈（仅开发环境）"
 * }
 * 
 * 环境差异：
 * - 开发环境：返回详细错误信息和堆栈跟踪
 * - 生产环境：返回简化错误信息，隐藏敏感信息
 * 
 * 使用示例：
 * // 在app.js中注册为最后一个中间件
 * app.use(errorHandler);
 * 
 * // 在路由中抛出错误
 * router.get('/test', (req, res, next) => {
 *   try {
 *     // 业务逻辑
 *     throw new Error('Something went wrong');
 *   } catch (error) {
 *     next(error); // 传递给错误处理中间件
 *   }
 * });
 * 
 * 安全考虑：
 * - 生产环境不暴露堆栈跟踪信息
 * - 过滤敏感信息如密码、令牌等
 * - 记录完整错误信息用于调试
 * - 返回用户友好的错误消息
 */
export const errorHandler = (err, req, res, next) => {
  // 第一步：记录错误日志 - Step 1: Log error details
  logger.error("错误处理中间件捕获错误 - Error handler caught error:", {
    message: err.message,
    stack: err.stack,
    url: req.url,
    method: req.method,
    ip: req.ip,
    userAgent: req.get('User-Agent'),
    timestamp: new Date().toISOString()
  });

  // 第二步：检查响应是否已经发送 - Step 2: Check if response already sent
  if (res.headersSent) {
    // 如果响应已经发送，将错误传递给Express默认错误处理器
    // If response already sent, pass error to Express default error handler
    return next(err);
  }

  // 第三步：提取错误状态码和消息 - Step 3: Extract error status and message
  const status = err.status || err.statusCode || 500;           // 错误状态码 - Error status code
  const message = err.message || '服务器内部错误 - Internal server error'; // 错误消息 - Error message

  // 第四步：构建错误响应对象 - Step 4: Build error response object
  const errorResponse = {
    success: false,                                             // 请求失败标识 - Request failure flag
    message: message,                                           // 错误消息 - Error message
    error: err.code || 'INTERNAL_SERVER_ERROR',                // 错误代码 - Error code
    timestamp: new Date().toISOString(),                       // 错误时间戳 - Error timestamp
    path: req.originalUrl || req.url,                          // 请求路径 - Request path
    method: req.method                                          // 请求方法 - Request method
  };

  // 第五步：根据环境添加调试信息 - Step 5: Add debug info based on environment
  if (process.env.NODE_ENV === 'development') {
    // 开发环境：包含详细的错误堆栈信息 - Development: include detailed stack trace
    errorResponse.stack = err.stack;
    errorResponse.details = {
      name: err.name,
      code: err.code,
      errno: err.errno,
      syscall: err.syscall
    };
  }

  // 第六步：根据错误类型进行特殊处理 - Step 6: Special handling based on error type
  if (err.name === 'ValidationError') {
    // 验证错误：提供详细的验证失败信息 - Validation error: provide detailed validation failure info
    errorResponse.message = '数据验证失败 - Data validation failed';
    errorResponse.error = 'VALIDATION_ERROR';
    errorResponse.validationErrors = err.errors;
  } else if (err.name === 'CastError') {
    // 类型转换错误：通常是数据库ID格式错误 - Cast error: usually database ID format error
    errorResponse.message = '数据格式错误 - Invalid data format';
    errorResponse.error = 'INVALID_DATA_FORMAT';
  } else if (err.code === 11000) {
    // MongoDB重复键错误 - MongoDB duplicate key error
    errorResponse.message = '数据已存在 - Data already exists';
    errorResponse.error = 'DUPLICATE_DATA';
  } else if (err.name === 'JsonWebTokenError') {
    // JWT令牌错误 - JWT token error
    errorResponse.message = '认证令牌无效 - Invalid authentication token';
    errorResponse.error = 'INVALID_TOKEN';
  } else if (err.name === 'TokenExpiredError') {
    // JWT令牌过期错误 - JWT token expired error
    errorResponse.message = '认证令牌已过期 - Authentication token expired';
    errorResponse.error = 'TOKEN_EXPIRED';
  }

  // 第七步：发送错误响应 - Step 7: Send error response
  res.status(status).json(errorResponse);
};

/**
 * ============404错误处理中间件开始===========
 * 404错误处理中间件 - 处理未找到的路由
 * 404 Error Handler Middleware - Handle not found routes
 * 
 * @param {Object} req - Express请求对象
 * @param {Object} res - Express响应对象
 * @param {Function} next - Express下一个中间件函数
 * @returns {void} 返回404错误响应
 * 
 * 功能说明：
 * - 处理所有未匹配的路由请求
 * - 返回标准化的404错误响应
 * - 记录404请求日志用于分析
 * - 提供友好的错误提示
 * 
 * 使用场景：
 * - 用户访问不存在的API端点
 * - 前端路由配置错误
 * - API版本更新后的旧端点访问
 * 
 * 使用示例：
 * // 在所有路由定义之后注册
 * app.use(notFoundHandler);
 * app.use(errorHandler);
 */
export const notFoundHandler = (req, res, next) => {
  // 记录404请求日志 - Log 404 request
  logger.warn("404错误 - 未找到请求的资源 - 404 Error - Requested resource not found:", {
    url: req.originalUrl,
    method: req.method,
    ip: req.ip,
    userAgent: req.get('User-Agent'),
    timestamp: new Date().toISOString()
  });

  // 构建404错误响应 - Build 404 error response
  const error = new Error(`未找到请求的资源: ${req.originalUrl} - Resource not found: ${req.originalUrl}`);
  error.status = 404;
  error.code = 'RESOURCE_NOT_FOUND';

  // 传递给错误处理中间件 - Pass to error handler middleware
  next(error);
};

/**
 * ============异步错误包装器开始===========
 * 异步错误包装器 - 包装异步路由处理器
 * Async Error Wrapper - Wrap async route handlers
 * 
 * @param {Function} fn - 异步路由处理函数
 * @returns {Function} 包装后的路由处理函数
 * 
 * 功能说明：
 * - 自动捕获异步函数中的错误
 * - 将错误传递给错误处理中间件
 * - 简化异步路由的错误处理代码
 * - 防止未处理的Promise拒绝
 * 
 * 使用示例：
 * import { asyncHandler } from './middleware/errorHandler.js';
 * 
 * router.get('/users', asyncHandler(async (req, res) => {
 *   const users = await User.find();
 *   res.json(users);
 * }));
 * 
 * 优势：
 * - 无需在每个异步路由中写try-catch
 * - 统一的错误处理流程
 * - 减少代码重复
 * - 提高代码可读性
 */
export const asyncHandler = (fn) => {
  return (req, res, next) => {
    // 执行异步函数并捕获任何错误 - Execute async function and catch any errors
    Promise.resolve(fn(req, res, next)).catch(next);
  };
};

/**
 * ============中间件导出说明开始===========
 * 导出错误处理中间件供应用使用
 * Export error handling middleware for app use
 * 
 * 导出说明：
 * - errorHandler: 全局错误处理中间件
 * - notFoundHandler: 404错误处理中间件
 * - asyncHandler: 异步错误包装器
 * 
 * 使用示例：
 * import { errorHandler, notFoundHandler, asyncHandler } from './middleware/errorHandler.js';
 * 
 * // 注册中间件（顺序很重要）
 * app.use('/api', routes);           // 业务路由
 * app.use(notFoundHandler);          // 404处理
 * app.use(errorHandler);             // 全局错误处理
 * 
 * // 使用异步包装器
 * router.get('/data', asyncHandler(async (req, res) => {
 *   const data = await fetchData();
 *   res.json(data);
 * }));
 */
// ============错误处理中间件模块结束===========
